//------------------------------------------------------------------------------
// <copyright file="RpcSocketTransportMessage.cpp" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#include "stdafx.h"

#include "RpcSocketTransportMessage.h"

using namespace Microsoft::Internal::GamesTest::Rpc::Server;

const wchar_t ServerIdKey[] = L"serverId";
const wchar_t RpcMessageKey[] = L"rpcMessage";
const wchar_t ErrorCodeKey[] = L"errorCode";
const wchar_t VersionKey[] = L"version";

GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT RpcSocketTransportMessage::Parse(std::wstring data, RpcSocketTransportMessage* result)
{
	HRESULT hr = S_OK;

	VERIFY_PARAM_NOT_NULL(result);

	try
	{
		// Parse socket transport message
		JsonNode socketTransportMessage;
		socketTransportMessage.Parse(data);

		// Get server Id and convert to GUID
		std::wstring serverId = socketTransportMessage.GetStringValue(ServerIdKey);

		if (serverId.front() != L'{')
		{
			serverId.insert(serverId.begin(), L'{');
		}

		if (serverId.back() != L'}')
		{
			serverId.push_back(L'}');
		}

		CHK(CLSIDFromString(serverId.data(), &result->serverId));

		// Get higher-level RPC message JSON as a string
		result->rpcMessage = socketTransportMessage.GetStringValue(RpcMessageKey);

		// Get error code
		result->errorCode = (HRESULT)socketTransportMessage.GetNumericValue(ErrorCodeKey);

		// Get version
		result->version = socketTransportMessage.GetStringValue(VersionKey);
	}
	catch (std::out_of_range)
	{
		// Key not found error
		hr = E_INVALID_PROTOCOL_FORMAT;
		goto end;
	}
	catch (std::invalid_argument)
	{
		// Parse error
		if (data.empty())
		{
			hr = E_INVALIDARG;
		}
		else
		{
			hr = E_INVALID_PROTOCOL_FORMAT;
		}

		goto end;
	}	

end:
	return hr;
}

GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT RpcSocketTransportMessage::Serialize(std::wstring& serializedData)
{
	HRESULT hr = E_FAIL;
	JsonNode socketResponse;
	LPOLESTR serverIdString = nullptr;

	CHK(StringFromCLSID(serverId, &serverIdString));

	socketResponse.SetValue(ServerIdKey, serverIdString);
	socketResponse.SetValue(RpcMessageKey, rpcMessage);
	socketResponse.SetValue(ErrorCodeKey, errorCode);
	socketResponse.SetValue(VersionKey, version);

	serializedData = socketResponse.Serialize();

end:
	if(serverIdString != nullptr)
	{
		CoTaskMemFree(serverIdString);
	}

	return hr;
}